package com.fz.song.controller;

import com.fz.song.pojo.BigFile;
import com.fz.song.pojo.Result;
import com.fz.song.service.BigFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

@Controller
@CrossOrigin
public class UploadController {

    //文件上传路径
    private String _PATH = "d://app/bigfile/";
    private String SUFFIX = ".temp";

    @Autowired
    private BigFileService bigFileService;

    /**
     * 检查文件是否存在:用于秒传
     * 根据前台传递的文件的MD5值,去数据库查询这个文件是否已经存在了.
     *
     * @param filemd5
     * @return
     */
    @RequestMapping("checkfile")
    @ResponseBody
    public Result checkFile(String filemd5) {
        BigFile fileByMd5 = bigFileService.getFileByMd5(filemd5);
        if (fileByMd5 == null) {
            return Result.ok("文件不存在", false);
        }
        return Result.ok("文件已经存在", true);
    }


    /**
     * 检查文件分块是否存在:用于断点续传
     * 根据文件的MD5值,和分块的的下标去服务器找文件,找到后比较大小是否完整
     * 是存在d://app/bigfile/这个文件夹下,以MD5为名字的一个文件夹,里面存的是1.temp,2.temp...这样的临时文件
     *
     * @param filemd5
     * @param chunk
     * @param chunksize
     * @return
     */
    @RequestMapping("checkchunk")
    @ResponseBody
    public Result checkChunk(String filemd5, Integer chunk, Integer chunksize) {
        String path = _PATH + filemd5;
        File file = new File(path);
        if (!file.exists()) {
            return Result.ok("分块文件不存在", false);
        } else {
            String tempName = chunk + SUFFIX;
            File tempFile = new File(file, tempName);
            //文件存在而且大小相等
            if (tempFile.exists() && tempFile.length() == chunksize) {
                return Result.ok("分块文件存在", true);
            } else {
                return Result.ok("分块文件不存在", false);
            }
        }
    }

    /**
     * 上传文件分片
     *
     * @param file
     * @param chunks
     * @param chunk
     * @param filemd5
     * @return
     */
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    @ResponseBody
    public Object upload(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "chunks") int chunks,
            @RequestParam(value = "chunk") int chunk,
            @RequestParam(value = "filemd5") String filemd5
    ) {
        System.out.println("上传分块文件" + chunk);
        File dir = new File(_PATH + filemd5);
        if (!dir.exists()) {//如果文件夹不存在
            dir.mkdirs();//创建文件夹
        }
        try {
            byte[] bytes = file.getBytes();
            String tempName = chunk + SUFFIX;
            Path path = Paths.get(_PATH + filemd5 + File.separator + tempName);
            Files.write(path, bytes);

        } catch (IOException e) {
            e.printStackTrace();
        }
        Result result = Result.ok("分片上传完成");
        return result;
    }


    /**
     * 合并文件,就是根据文件的MD5值站到临时文件夹,然后遍历这些文件,一个一个写到文件中,然后存一个记录到数据库中
     *
     * @param filemd5
     * @param filename
     * @return
     */
    @RequestMapping(value = "/merge", method = RequestMethod.POST)
    @ResponseBody
    public Result merge(@RequestParam("filemd5") String filemd5, @RequestParam("filename") String filename) {
        Result result = null;
        File dir = new File(_PATH + filemd5);
        if (dir.exists()) {
            File[] files = dir.listFiles();
            List<File> fileList = Arrays.asList(files);
            //按名字排序.
            Collections.sort(fileList, new Comparator<File>() {
                @Override
                public int compare(File o1, File o2) {
                    if (o1.isDirectory() && o2.isFile()) {
                        return -1;
                    }
                    if (o1.isFile() && o2.isDirectory()) {
                        return 1;
                    }
                    String name1 = o1.getName();
                    String[] split1 = name1.split("\\.");
                    String name2 = o2.getName();
                    String[] split2 = name2.split("\\.");
                    return Integer.parseInt(split1[0]) - Integer.parseInt(split2[0]);
                }
            });
            try {
                //写入大文件的输出流
                File file2 = new File(_PATH + filename);
                OutputStream out = new FileOutputStream(file2, true);
                Long filesize = 0l;
                for (File file : fileList) {
                    filesize += file.length();
                    System.out.println(file.getAbsolutePath());
                    //读取小文件的输入流
                    InputStream in = new FileInputStream(file);
                    int len = -1;
                    byte[] bytes = new byte[5 * 1024 * 1024];
                    while ((len = in.read(bytes)) != -1) {
                        out.write(bytes, 0, len);
                    }

                    in.close();
                    file.delete();
                }
                out.close();
                dir.delete();
                BigFile bigFile = new BigFile();
                bigFile.setFileName(filename);
                bigFile.setFilePath(file2.getPath());
                bigFile.setFileSize(filesize);
                bigFile.setFileMd5(filemd5);
                bigFileService.save(bigFile);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            result = Result.ok("合并成功", true);
        } else {
            result = Result.fail(1, "未找到缓存文件");
        }
        return result;
    }


}
